#include "decoder.h"
#include "string.h"
#include "tim.h"
#include "st7735.h"

#define DECODER_TIM_STRUCT htim3
#define DECODER_TIM_CHANNEL TIM_CHANNEL_1

struct Decoder decoder;

void decoder_parse(void);

void decoder_init() {
  decoder.length = 0;
  // IC
  HAL_TIM_IC_Start_IT(&DECODER_TIM_STRUCT, TIM_CHANNEL_1);
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
  if (htim->Instance == TIM3) {
    uint32_t ICT = HAL_TIM_ReadCapturedValue(&DECODER_TIM_STRUCT, DECODER_TIM_CHANNEL);
    __HAL_TIM_SET_COUNTER(htim, 0);

    if (HAL_GPIO_ReadPin(RF_GPIO_Port, RF_Pin) == GPIO_PIN_SET) {
      // rising edge
      if (ICT > 15000) {
        // unknown
        decoder.length = 0;
      } else if (ICT > 5000) {
        // data copy----------------------------------------------------------------
        memcpy(decoder.period_buffer, decoder.period, decoder.length * 2);
        decoder.length_buffer = decoder.length;

        decoder_parse();
        // decode copy------------------------------------------------------------------

        decoder.length = 0;
        decoder.period[decoder.length++] = ICT;
      } else if (decoder.length) {
        // data
        decoder.period[decoder.length++] = ICT;
      }
    } else {
      // falling edge
      if (decoder.length) {
        // data
        decoder.period[decoder.length++] = ICT;
      }
    }

    if (decoder.length >= DECODER_MAX_LENGTH) {
      decoder.length = DECODER_MAX_LENGTH;
    }
  }
}

void decoder_parse() {
  if (decoder.length_buffer < 32) {
    return;
  }

  // parse
  decoder.data = 0;
  for (uint8_t i = 0; i < decoder.length_buffer; i += 2) {
    decoder.data <<= 1;
    decoder.data |= (decoder.period_buffer[i] > decoder.period_buffer[i + 1]) ? 1 : 0;
  }
  decoder.cnt++;

  LED;

  // clear
  ST7735_Rectangle(0, 0, 70, ST7735_HEIGHT, ST7735_BLACK);
  // display period
  uint8_t pos_x = 0, pos_y = 0;
  for (uint8_t i = 0; i < DECODER_MAX_LENGTH; i += 2) {
    if (i == 0) {
      decoder.lead = decoder.period[i];
      continue;
    }

    sprintf(decoder.info, "%04d ", decoder.period_buffer[i]);
    ST7735_String(pos_x, pos_y, decoder.info, ST7735_RED, ST7735_BLACK, &font_small);

    sprintf(decoder.info, "%04d ", decoder.period_buffer[i + 1]);
    ST7735_String(pos_x + font_small.width * 5, pos_y, decoder.info, ST7735_BLUE, ST7735_BLACK, &font_small);

    if (i % 2 == 0) {
      pos_y += font_small.height;
    }

    if (pos_y >= ST7735_HEIGHT) {
      pos_x += font_small.width * 10;
      pos_y = 0;
    }

    if (pos_x >= 70) {
      break;
    }
  }

  // info
  sprintf(decoder.info, "CNT:%d", decoder.cnt);
  ST7735_String(80, font_small.height * 0, decoder.info, ST7735_WHITE, ST7735_BLACK, &font_small);
  sprintf(decoder.info, "LEN:%d", decoder.length_buffer);
  ST7735_String(80, font_small.height * 1, decoder.info, ST7735_GREEN, ST7735_BLACK, &font_small);
  sprintf(decoder.info, "LEAD:%05d", decoder.lead);
  ST7735_String(80, font_small.height * 2, decoder.info, ST7735_GREEN, ST7735_BLACK, &font_small);

  sprintf(decoder.info, "0x%08X", decoder.data);
  ST7735_String(80, font_small.height * 4, decoder.info, ST7735_GREEN, ST7735_BLACK, &font_small);

  LED_NONE;
}
